package comframe.jdbc.sql.convert;

import java.io.BufferedReader;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.Clob;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 通过反射获取字段值   
 * 字段方法必须符合javaBean规则
 * @author ray
 *
 */
public class ConvertUtil {
	/**
	 * 获得对象的值
	 * @param object
	 * @param name
	 * @return
	 */
	public static Object getProperty(Object object,String name){
		Class<? extends Object> clazz = object.getClass();
		Object value = null;
			try {
				Method method = clazz.getMethod(MethodUtil.creatGetMethod(name), null);
				value = method.invoke(object, null);
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				
				e.printStackTrace();
			}
		
		return value;
	}
	
	/**
	 * 获得对象的值
	 * @param object
	 * @param name
	 * @return
	 */
	public static Object getProperty(Object object,String name,Class<?> clazzType){
		Class<? extends Object> clazz = object.getClass();
		Object value = null;
			try {
				Method method = clazz.getMethod(MethodUtil.creatGetMethod(name), null);
				value = method.invoke(object, null);
				if(Date.class == clazzType && value != null){
					value = new Timestamp(((Date)value).getTime());
				}
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				
				e.printStackTrace();
			}
		
		return value;
	}
	
	
	/**
	 * 获得对象的值
	 * @param object
	 * @param name
	 * @return
	 */
	public static String getTimeString(Object object,String name,String timeTemp){
		Class<? extends Object> clazz = object.getClass();
		Date date = null;
		String value = "";
			try {
				Method method = clazz.getMethod(MethodUtil.creatGetMethod(name), null);
				date = (Date) method.invoke(object, null);
				if(date == null) return null;
				value = new SimpleDateFormat(timeTemp).format(date);
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				
				e.printStackTrace();
			}
		
		return value;
	}
    /**
     * 结果集转对象
     * @param resultSet
     * @param clazz
     * @return
     * @throws SQLException 
     * @throws IllegalAccessException 
     * @throws InstantiationException 
     */
	public static List<Object> RsConverToObject(ResultSet rs,
			Class<?> cls) throws SQLException, InstantiationException, IllegalAccessException {
		List<Object> result = new ArrayList<Object>();
		Object object = null;

		
		while (rs.next()) {
			if(cls == Map.class || cls == HashMap.class){
				Map<String, Object> map = new HashMap<String, Object>();
				for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) {
					// 保存字段名称
					String columnName = rs.getMetaData().getColumnName(i + 1)
							.toLowerCase();
					// 匹配字段 并获取字段属性
					setMapValue(columnName,map,rs,i);
				}
				result.add(map);
			}else{
				object = cls.newInstance();
				for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) {
					// 保存字段名称
					String columnName = rs.getMetaData().getColumnName(i + 1)
							.toLowerCase();
					// 匹配字段 并获取字段属性
					setObjectValue(columnName,cls,object,rs,i);
				}
				result.add(object);
			}
		}
		rs.close();
		return result;
	}
  
	private static void setMapValue(String columnName,Map<String,Object> map,ResultSet rs,int i) {
		try {
			
			int types = rs.getMetaData().getColumnType(i + 1);
			Object _object = rs.getObject(columnName);
			//防止取时间类型是 丢失时间
			if (types == Types.DATE) {
				_object = rs.getTimestamp(columnName);
				types = Types.TIMESTAMP;
			}else if(types == Types.CLOB){
				_object = rs.getClob(columnName);
			}
			map.put(columnName, _object);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	

	private static void setObjectValue(String columnName,Class<?> cls, Object object,ResultSet rs,int i) {
		try {
			Field[] fields = cls.getDeclaredFields();
			for (Field f : fields) {
				if (f.getName().toLowerCase().equals(columnName)) {
					columnName = f.getName().substring(0, 1)
							.toUpperCase() + f.getName().substring(1);
					Method method = cls.getDeclaredMethod("set"
							+ columnName, new Class[] { f.getType() });
					int types = rs.getMetaData().getColumnType(i + 1);
					
					Object _object = rs.getObject(columnName);
					//防止取时间类型是 丢失时间
					if (types == Types.DATE) {
						_object = rs.getTimestamp(columnName);
						types = Types.TIMESTAMP;
					}else if(types == Types.CLOB){
						_object = rs.getClob(columnName);
					}
					// 转换对象
					Object params = ConvertType(_object, types, f.getType());
					method.invoke(object, params);
					break;
				}
			}
			if(cls.getSuperclass() != null){
				setObjectValue(columnName, cls.getSuperclass(), object, rs, i);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * DATE Timestamp 相互转换
	 * 
	 * @param ConverObject
	 *            转换对象
	 * @param types
	 *            转变对象类型
	 * @param Type
	 *            目标类型
	 * @return
	 * @throws NoSuchMethodException
	 * @throws SecurityException
	 * @throws InvocationTargetException
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 * @throws IllegalArgumentException
	 * @throws SQLException
	 * @throws IOException 
	 */
	private static Object ConvertType(Object ConverObject, int types, Class<?> Type)
			throws SecurityException, NoSuchMethodException,
			IllegalArgumentException, InstantiationException,
			IllegalAccessException, InvocationTargetException, SQLException, IOException {
		Object object = null;
		//当对象不为空的时候
		if(ConverObject != null){
			//转成Float
			if(Float.class==Type||float.class==Type){
				 object = TypeConvertUtil.StringToFloat(ConverObject.toString());
			}else if(Integer.class==Type||int.class==Type){
				 object = TypeConvertUtil.StringToInteger(ConverObject.toString());
			}else if(BigDecimal.class==Type){
				 object = TypeConvertUtil.StringToBigDecimal(ConverObject.toString());
			}else if(Date.class == Type){
				if(oracle.sql.TIMESTAMP.class == ConverObject.getClass()){
					object = new Date(((oracle.sql.TIMESTAMP)ConverObject).timestampValue().getTime());
				}else if(Timestamp.class == ConverObject.getClass()){
					object = new Date(((Timestamp)ConverObject).getTime());
				}else{
					object = ConverObject;
				}
			}else if(Timestamp.class == Type){
				object = ConverObject;
			}else if (String.class == Type){
				object = ConverObject.toString();
				if(types == Types.CLOB){
						BufferedReader br = new BufferedReader(((Clob)ConverObject).getCharacterStream());
						StringBuffer sb = new StringBuffer();
						String str= br.readLine();
						while(str!=null){
							sb.append(str);
							str = br.readLine();
						}
						br.close();
						object = sb.toString();
				}
			}else{
				object = ConverObject;
			}
		}

		return object;
	}
	/**
	 * 结果集转成Integer
	 * @param executeQuery
	 * @param clazz
	 * @return
	 * @throws SQLException 
	 */
	public static Integer RsConverToCount(ResultSet rs, Class<?> clazz) throws SQLException {
		Integer sum = 0;
		while (rs.next()){
		  sum = rs.getInt(1);	
		}
		rs.close();
		return sum;
	}

}
